#pragma once

struct ECameraUpdateFlag
{
	enum Flag
	{
	    ViewportChanged			= 1 << 0,
	    ViewMatrixChanged		= 1 << 1,
	    ProjectionMatrixChanged	= 1 << 2,
	    FrustumChanged			= 1 << 3
	};
};

class ICamera
{
public:
	ICamera();
	ICamera(float farDist, float nearDist);
	virtual ~ICamera();

	/*--------------------------------------------------------------------------*/
	virtual bool		Update() = 0;
	virtual bool		IsVisible(const glm::vec3& space, const float& radius) const = 0;
	virtual glm::vec2	GetOnScreenCoords(const glm::mat4& modelmatrix, const glm::vec3& pnt, bool* visible) const = 0;
	/*--------------------------------------------------------------------------*/

	const glm::mat4&	GetViewMatrix();
	const glm::mat4&	GetInvViewMatrix();
	const glm::mat4&	GetViewProjectionMatrix();
	const glm::mat4&	GetInvViewProjectionMatrix();
	const glm::mat4&	GetProjectionMatrix();
	const glm::mat4&	GetInvProjectionMatrix();

	const glm::vec4&	GetViewport() const;
	void				SetViewport(const glm::vec4& size);

	const float&		GetNearDistance() const;
	void				SetNearDistance(const float& nval);

	const float&		GetFarDistance() const;
	void				SetFarDistance(const float& nval);

	const glm::vec3&	GetPosition() const;
	void				SetPosition(const glm::vec3& position);

	const glm::vec3&	GetViewDirection() const;
	const glm::vec3&	GetStrafeDirection() const;
	const glm::vec3&	GetJumpDirection() const;

protected:
	/*--------------------------------------------------------------------------*/
	virtual bool		UpdateProjectionMatrix() = 0;
	virtual bool		UpdateViewMatrix() = 0;
	/*--------------------------------------------------------------------------*/

	glm::vec4			m_viewport;
	glm::vec3			m_position;

	float				m_farDistance;
	float				m_nearDistance;

	glm::mat4			m_projectionMatrix;
	glm::mat4			m_invProjectionMatrix;

	glm::mat4			m_viewMatrix;
	glm::mat4			m_invViewMatrix;

	glm::mat4			m_viewProjectionMatrix;
	glm::mat4			m_invViewProjectionMatrix;

	unsigned int		m_updateFlags;

	glm::vec3			m_viewdirection;
	glm::vec3			m_strafedirection;
	glm::vec3			m_jumpdirection;
};